#define E_I2C_SALVE
#include "H/I2C_SALVE.H"

/*****************************************************
*函数名称：void I2C_SALVE_INT(uchar *P_ADDR,uchar R_LENGTH)
*函数功能：I2C从机发送模式中断服务函数
*入口参数：uchar *P_ADDR   指向发送数据首地址
           uchar R_LENGTH  发送数据长度
*出口参数：void
*****************************************************/
void I2C_SALVE_INT(uchar *P_ADDR,uchar R_LENGTH)
{
    F_I2C_S=0;   //总线忙 
    R_I2C_S_OVERTIME=0;
    if(F_I2C_S_START==0)
    {
        F_I2C_S_START=1;
        R_I2C_S_DATA_LENGTH=0;
        F_I2C_S_ERR=0;   //通讯失败标志清0
        P_I2C_S_DATA=P_ADDR;
    }
    if(GET_I2CWR)	  
    {
        //从机发送
        if(CHECK_SALVE_I2CESTA())
        {    
            //状态错误         
            F_I2C_S_ERR=1; //通讯失败
        }
        else
        {
            //状态正确
            I2CDAT=*P_I2C_S_DATA++;
            R_I2C_S_DATA_LENGTH++;
            if(R_I2C_S_DATA_LENGTH==R_LENGTH)
            {
                P_I2C_S_DATA=P_ADDR;
                R_I2C_S_DATA_LENGTH=0;
                F_I2C_S=1;//总线空闲
            }
        }   
    }
    else
    {}//从机接收       
}

/*****************************************************
*函数名称：void I2C_SALVE_INIT(uchar R_ADDR)
*函数功能：I2C初始化,从机模式
*入口参数：uchar R_ADDR  从机地址
*出口参数：void
*****************************************************/
void I2C_SALVE_INIT(uchar R_ADDR)
{    
    MAP0 &=~0x30;
    MAP0 =I2CSDAM(D_S_SDA)|I2CSCLM(D_S_SCL);
    I2C_SDA_IN;//SDA做输入口
    I2C_SCL_IN;//SCL做输入口

    I2C_SCL_OD_ON; //SCL开漏使能
    I2C_SDA_OD_ON; //SDA开漏使能  
                 
    I2CCON0=I2CEN_EN|I2CMOD(0)|I2CIE(1)|GC(1);//I2C使能|从机模式|中断设置|广播地址应答
    I2CCON1=I2CADR(R_ADDR)  ;//本机通讯地址02H
    F_I2C_S_START=0;  //首次进I2C中断
    F_I2C_S_OVERTIME=0;//未超时
    R_I2C_S_OVERTIME=0;
    F_I2C_S=1;  //总线空闲
}
/*****************************************************
*函数名称：void I2C_START()
*函数功能：发送起始位
*入口参数：void
*出口参数：void
*****************************************************/
void I2C_START()
{ 
    I2CSTO = 0;
    I2CSTA = 1;
}

/*****************************************************
*函数名称：void I2C_STOP()
*函数功能：发送停止位
*入口参数：void
*出口参数：void
*****************************************************/
void I2C_STOP()
{
    I2CSTA = 0;
    I2CSTO = 1;
}

/*****************************************************
*函数名称：bit CHECK_SALVE_I2CESTA()
*函数功能：I2C错误状态返回，=1状态错误
*入口参数：void
*出口参数：void
*****************************************************/
bit CHECK_SALVE_I2CESTA()
{
    uchar R_I2CSTATE;
    R_I2CSTATE=I2CSTATE&0X07;
    F_I2C_S_STA=0;
    switch(R_I2CSTATE)
    {               
//    case 1://主机模式下地址不匹配,从机回NACK         
//    case 2://主机模式下发数据时,从机回NACK
//        F_I2C_M_STA=1;
//        break;
    case 3://从机发送模式下，主机回NACK
        F_I2C_S_ERR=1;
        break;
    default : break;
    }
    return  F_I2C_S_STA;
}

/*****************************************************
*函数名称：void I2C_S_OVERTIME(uchar R_OVERTIME)
*函数功能：I2C超时判断，超时范围设置1~255，超时时间=调用时间*R_OVERTIME
*入口参数：uchar R_OVERTIME 超时时间设置
*出口参数：void
*****************************************************/
void I2C_S_OVERTIME(uchar R_OVERTIME)
{
    if(F_I2C_S==0)  //总线忙
    {
        R_I2C_S_OVERTIME++;        //超时计数，与调用时间有关，需用户自行确认
        if(R_I2C_S_OVERTIME>=R_OVERTIME)
        {
            //超时，总线长时间未释放，I2C 关闭
            I2CCON0=I2CEN_DIS|I2CMOD(0)|I2CIE(1);//I2C不使能|从机模式|中断使能           
            F_I2C_S_ERR=1;     //1：通讯失败 
            F_I2C_S_OVERTIME=1;//1：超时  
            F_I2C_S=1;         //总线空闲  
            F_I2C_S_START=0;  
            I2CCON0=I2CEN_EN|I2CMOD(0)|I2CIE(1)|GC(1);//I2C使能|从机模式|中断设置|广播地址应答     
        }  
    }            
}












